<template>
  <div class="vk-form-item">
    <label class="vk-form-item__label">
      {{ label }}
    </label>
    <div class="vk-form-item__content">
      <slot/>
      <template v-if="validateStatus.state==='error'">{{ validateStatus.errorMsg }}</template>
    </div>
  </div>
</template>

<script setup lang="ts">
import {isNil} from "lodash-es";
import Schema from "async-validator";
import {formContextKey, formItemContextKey} from "./types";
import type {FormItemProps, ValidateStatusProp, FormValidateFailure, FormItemContext, FormItemInstance} from "./types"
import {inject, provide, computed, reactive, onMounted, onUnmounted} from "vue";

defineOptions({
  name: 'VKFormItem'
})
const props = defineProps<FormItemProps>()
const formContext = inject(formContextKey);
const validateStatus = reactive<ValidateStatusProp>({
  state: 'init',
  errorMsg: '',
  loading: false
})
let initialValue: any = null
const innerValue = computed(() => {
  const model = formContext?.model
  if (model && props.prop && !isNil(model[props.prop])) {
    return model[props.prop]
  } else {
    return null;
  }
})
const itemRules = computed(() => {
  const rules = formContext?.rules
  if (rules && props.prop && rules[props.prop]) {
    return rules[props.prop]
  } else {
    return [];
  }
})
const getTriggeredRules = (trigger?: string) => {
  const rules = itemRules.value
  if (rules) {
    return rules.filter(rule => {
      if (!rule.trigger || !trigger) return true
      return rule.trigger && rule.trigger === trigger
    })
  } else {
    return []
  }
}
onMounted(() => {
  if (props.prop) {
    formContext?.addField(context)
    initialValue = innerValue.value
  }
})
onUnmounted(() => {
  formContext?.removeField(context)
})
const validate = async (trigger?: string) => {
  const triggeredRules = getTriggeredRules(trigger)
  if (triggeredRules.length === 0) return true
  const modelName = props.prop
  if (modelName) {
    const validator = new Schema({[modelName]: triggeredRules})
    return validator.validate({[modelName]: innerValue.value}).then(res => {
      validateStatus.state = 'success'
      console.log('success')
    }).catch((e: FormValidateFailure) => {
      const {errors} = e
      validateStatus.state = 'error'
      validateStatus.errorMsg = (errors && errors.length) ? errors[0].message || '' : ''
      console.log(e.errors)
      return Promise.reject(e)
    }).finally(() => {
      validateStatus.loading = false
    })
  }
}
const clearValidate = () => {
  validateStatus.state = 'init'
  validateStatus.errorMsg = ''
  validateStatus.loading = false
}
const resetField = () => {
  clearValidate()
  const model = formContext?.model
  if (model && props.prop && !isNil(model[props.prop])) {
    model[props.prop] = initialValue
  }

}
const context: FormItemContext = {
  validate,
  prop: props.prop || '',
  clearValidate,
  resetField
}
provide(formItemContextKey, context)

defineExpose<FormItemInstance>({
  validateStatus,
  validate,
  resetField,
  clearValidate
})
</script>

<style scoped>

</style>
